package com.symaster.common.swing.entity;

import com.symaster.common.swing.config.AppConfig;
import com.symaster.common.swing.style.Style;
import com.symaster.common.swing.util.ThreadPoolUtil;
import com.symaster.common.util.CommonUtil;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Set;

public class MessageItem extends JPanel {

    private final String message;
    private final int type;
    private JTextField textField;
    private int messageWidth;
    private Integer lineHeight;
    private Boolean selectDisable;
    private Integer width;
    private Set<ClickListener> clickListeners;
    private Date time;
    private String timeFormat;
    private Boolean showTime;

    public MessageItem(String message, int type) {
        this.message = message;
        this.type = type;
        initItem(message, type);
        initListener();
    }

    public MessageItem(String message, int type, int lineHeight) {
        this.message = message;
        this.type = type;
        this.lineHeight = lineHeight;
        initItem(message, type);
        initListener();
    }

    public MessageItem(String message, int type, int lineHeight, boolean selectDisable) {
        this.message = message;
        this.type = type;
        this.lineHeight = lineHeight;
        this.selectDisable = selectDisable;
        initItem(message, type);
        initListener();
    }

    public MessageItem(String message, int type, int lineHeight, boolean selectDisable, Boolean showTime) {
        this.message = message;
        this.type = type;
        this.lineHeight = lineHeight;
        this.selectDisable = selectDisable;
        this.showTime = showTime;
        initItem(message, type);
        initListener();
    }

    public MessageItem(String message, int type, int lineHeight, boolean selectDisable, Boolean showTime, String timeFormat) {
        this.message = message;
        this.type = type;
        this.lineHeight = lineHeight;
        this.selectDisable = selectDisable;
        this.showTime = showTime;
        this.timeFormat = timeFormat;
        initItem(message, type);
        initListener();
    }

    public Integer getItemWidth() {
        return width;
    }

    private void initItem(String message, int type) {

        this.time = new Date();

        if (showTime != null && showTime) {
            if (StringUtils.isEmpty(timeFormat)) {
                message = String.format("[%s] %s", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time), message);
            } else {
                message = String.format("[%s] %s", new SimpleDateFormat(timeFormat).format(time), message);
            }
        }

        textField = new JTextField(message);
        Font font = Style.getFont(1);
        messageWidth = CommonUtil.stringWidth(font, message);
        setLayout(new BorderLayout());
        textField.setEditable(false);
        if (selectDisable != null && selectDisable) {
            textField.setEnabled(false);
        }
        if (type == 1) {
            textField.setForeground(AppConfig.getColor("error_color"));
            textField.setDisabledTextColor(AppConfig.getColor("error_color"));
        } else {
            textField.setForeground(AppConfig.getColor("auxiliary_font_color"));
            textField.setDisabledTextColor(AppConfig.getColor("auxiliary_font_color"));
        }
        Style.setFont(1, textField);
        Style.setBorder(1, textField);

        add(textField, BorderLayout.CENTER);

        addAncestorListener(new AncestorListener() {
            @Override
            public void ancestorAdded(AncestorEvent event) {
                Container parent = getParent();
                textField.setBackground(parent.getBackground());

                extracted(parent);

                parent.addComponentListener(new ComponentListener() {
                    @Override
                    public void componentResized(ComponentEvent e) {
                        extracted(parent);
                    }

                    @Override
                    public void componentMoved(ComponentEvent e) {

                    }

                    @Override
                    public void componentShown(ComponentEvent e) {

                    }

                    @Override
                    public void componentHidden(ComponentEvent e) {

                    }
                });
            }

            @Override
            public void ancestorRemoved(AncestorEvent event) {

            }

            @Override
            public void ancestorMoved(AncestorEvent event) {

            }
        });
    }

    private void extracted(Container parent) {
        Dimension size = parent.getSize();

        int max = Math.max(messageWidth, (int) size.getWidth());
        this.width = max;
        if (lineHeight == null) {
            lineHeight = 28;
        }
        Dimension dimension = new Dimension(max, lineHeight);
        setPreferredSize(dimension);
        setMinimumSize(dimension);
    }

    private void initListener() {
        this.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                clickListener();
            }

            @Override
            public void mousePressed(MouseEvent e) {

            }

            @Override
            public void mouseReleased(MouseEvent e) {

            }

            @Override
            public void mouseEntered(MouseEvent e) {

            }

            @Override
            public void mouseExited(MouseEvent e) {

            }
        });
        textField.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                clickListener();
            }

            @Override
            public void mousePressed(MouseEvent e) {

            }

            @Override
            public void mouseReleased(MouseEvent e) {

            }

            @Override
            public void mouseEntered(MouseEvent e) {

            }

            @Override
            public void mouseExited(MouseEvent e) {

            }
        });
    }

    private void clickListener() {
        if (clickListeners == null) {
            return;
        }

        ThreadPoolUtil.execute(() -> {
            for (ClickListener clickListener : clickListeners) {
                clickListener.handle();
            }
        });
    }

    public String getMessage() {
        return message;
    }

    public int getType() {
        return type;
    }

    public void addClickListener(ClickListener listener) {
        if (clickListeners == null) {
            clickListeners = new HashSet<>();
        }
        clickListeners.add(listener);
    }

    public void removeClickListener(ClickListener listener) {
        if (clickListeners == null || clickListeners.size() <= 0) {
            return;
        }
        clickListeners.remove(listener);
    }

    public interface ClickListener extends EventListener {
        void handle();
    }
}